#include "cmdshop.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_SHOP_GET_INFO, CCmdGetShopInfo);
int CCmdGetShopInfo::Do(void* pData)
{
    //int iRet = 0;
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_SHOP_GET_INFO ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_SHOP_GET_INFO,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdGetShopInfo::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    ASSERT_PLAYER_PREPARED(stReq.gid());

    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo & stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo & stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NOT_LOGIN);
    }
    CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    unsigned char ucShopType = (unsigned char)(stReq.shop_type() & 0X7F);

    if (ucShopType == CShopMgr::SHOP_TYPE_MYSTICAL)
    {
        //检查系统是否开启
        if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_31, stPlayerBaseInfo, stPlayerOnlineData))
        {
            return AnsClients(ERROR_SYS_NOT_OPEN);
        }
    }

    iRet = CheckUpdate(stPlayerDetailInfo, stPlayerOnlineData);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    stPlayerOnlineData._stUserShop._stClanShop._uiClanId = stPlayerDetailInfo._stUserClan._uiClanId;
    iRet = pstMainCtrl->m_stShopMgr.GetShopInfo(stPlayerBaseInfo._shLevel,  stPlayerOnlineData._stUserShop,
                                                ucShopType, stAns);
    return AnsClients(iRet);
}

int CCmdGetShopInfo::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

int CCmdGetShopInfo::CheckUpdate (CPlayerDetailInfo & stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData)
{
    unsigned char ucShopType = (unsigned char)(stReq.shop_type() & 0X7F);
    int iRet = RET_OK;
    bool bNeedUpdateDetail = false;
    if (CShopMgr::SHOP_TYPE_CLAN == ucShopType)
    {
        iRet = pstMainCtrl->m_stClanMgr.RefreshShop (stPlayerDetailInfo._stUserClan._uiClanId);
        CHECK_RETURN(iRet);

        //每天23:00重置购买到的物品
        if ((!CTTimeUtils::IsSameDay(pstMainCtrl->m_iNow, stPlayerOnlineData._stUserShop._stClanShop._iLastBuyTime, MAX_CLAN_SHOP_REFRESH_TIME))
            || (stPlayerOnlineData._stUserShop._stClanShop._iLastBuyTime < stPlayerDetailInfo._stUserClan._iJoinTime))  //加入了不同的家族
        {
            stPlayerOnlineData._stUserShop._stClanShop._astBuyItems.Clear();
            stPlayerOnlineData._stUserShop._stClanShop._iLastBuyTime = CMainCtrl::m_pstMain->m_iNow;

            bNeedUpdateDetail = true;
        }
    }

    //检查是否需要清除已购买的魔晶商店物品
    if (CShopMgr::SHOP_TYPE_CRYSTAL == ucShopType)
    {   
        if (false == pstMainCtrl->m_stActMgr.IsActOpen(ACT_ID_WEEKEND_SHOP))
        {
            return ERROR_ACT_NOT_OPEN;
        }
        
        if (pstMainCtrl->m_iNow > stPlayerOnlineData._stUserShop._iClearCrystalShopTime)
        {
            int iActEndTime = pstMainCtrl->m_stActMgr.GetEndTime(ACT_ID_WEEKEND_SHOP);

            CT_WARNING (("%d, %d, %d", stPlayerDetailInfo._uiGID, stPlayerOnlineData._stUserShop._iClearCrystalShopTime, iActEndTime));

            stPlayerOnlineData._stUserShop._astCrystalItems.Clear();
            stPlayerOnlineData._stUserShop._iClearCrystalShopTime = iActEndTime;
            
            bNeedUpdateDetail = true;            
        }
    }

    if (bNeedUpdateDetail)
    {
        pstMainCtrl->m_stShopMgr.GetData(stPlayerOnlineData._stUserShop, stPlayerDetailInfo._stShopData);

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        CMainCtrl::m_pstMain->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    return RET_OK;
}

//////////////////////////////////////////////////////////////////////////

CT_REGISTER_ASYNCCMD(ID_MAIN_SHOP_BUY, CCmdShopBuyItem);
int CCmdShopBuyItem::Do(void* pData)
{
    //int iRet = 0;
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_SHOP_BUY ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_SHOP_BUY,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();
    _uiNotify = 0;
    iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
	return RET_OK;
}

int CCmdShopBuyItem::LogicDo(int iRet)
{
    unsigned char ucShopType = stReq.shop_type() & 0x7F;
    unsigned short usItemPos = stReq.item_pos() & 0x7FFF;

    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    ASSERT_PLAYER_PREPARED(stReq.gid());

    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    ASSERT_PLAYER_DETAIL_PREPARED(stReq.gid());

    PREPARE_PLAYER_SNS_DETAIL_INFO(this, stReq.gid());
    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
	CPlayerBaseInfo & stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo & stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

	iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
	CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    iRet = PreCheck(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    if (stReq.shop_type() == CShopMgr::SHOP_TYPE_MYSTICAL)
    {
        //检查系统是否开启
        if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_31, stPlayerBaseInfo, stPlayerOnlineData))
        {
            return AnsClients(ERROR_SYS_NOT_OPEN);
        }
    }

    pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss

	// 扣除货币
    switch(stShopConfigData._ucBuyType)
    {
    case ITEM_TYPE_GOLD:
        {            
            iRet = pstMainCtrl->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_51, stShopConfigData._iExchangeItemCount);
        }
        break;
    case ITEM_TYPE_SILVER:
        {
            if (CShopMgr::SHOP_TYPE_BUYBACK == ucShopType)
            {
                iRet = pstMainCtrl->m_stItemMgr.SubSilver(stPlayerBaseInfo, stShopConfigData._iExchangeItemCount, OSS_MONEY_MODULE_59);
            }
            else
            {
                iRet = pstMainCtrl->m_stItemMgr.SubSilver(stPlayerBaseInfo, stShopConfigData._iExchangeItemCount, 0);
            }
        }
        break;
#if 0
    case SHOP_BUY_TYPE_EXCHANGE:
        {
            iRet = CMainCtrl::m_pstMain->m_stStorageMgr.TakeOutItem(stPlayerOnlineData._stUserStorage,
                                             stShopConfigData._ucExchangeItemType, stShopConfigData._usItemConfigID,
                                              stShopConfigData._iExchangeItemCount);
        }
        break;
#endif
    case ITEM_TYPE_CONTRIBUTION:
        {
            iIndex = pstMainCtrl->m_stPlayerSnsDetailInfoHash.HashFind(stReq.gid());
            if (iIndex < 0)
            {
                return AnsClients(RET_NO_USER);
            }
            CPlayerSnsDetailInfo & stPlayerSnsDetailInfo = pstMainCtrl->m_stPlayerSnsDetailInfoHash[iIndex];

            if (stPlayerSnsDetailInfo._stCommInfo._iContribution < stShopConfigData._iExchangeItemCount)
            {
                return AnsClients(ERROR_SHOP_LACK_HONOR);
            }

            _uiNotify |= NOTIFY_ROLE_INFO;
            stPlayerSnsDetailInfo._stCommInfo._iContribution -= stShopConfigData._iExchangeItemCount;
            stAns.set_user_contribution(stPlayerSnsDetailInfo._stCommInfo._iContribution);

            CVarObjectKey stKey;
            stKey.m_chDataType = DT_PLAYER_SNS_DETAIL_INFO;
            stKey.m_u64ID = stPlayerSnsDetailInfo._uiGID;
            pstMainCtrl->UpdateData(stKey, stPlayerSnsDetailInfo, VOP_UPDATE);
        }
        break;
    default:
        return AnsClients(ERROR_SHOP_LACK_MONEY);
    }

    if (iRet)
    {
        return AnsClients(iRet);
    }

    if (CShopMgr::SHOP_TYPE_CRYSTAL == ucShopType)
    {
        int iRet = pstMainCtrl->m_stStorageMgr.TakeOutItem(stPlayerOnlineData._stUserStorage, ITEM_TYPE_SEAL, 1, stShopConfigData._usDiscount);
        if (iRet)
        {
            CT_ERROR(("%d, %d, %d, %d", _uiGID, stShopConfigData._usDiscount));
            return AnsClients(iRet);
        }
    }

    //发货
    CDropItemData stNewItem;
    if (ITEM_TYPE_EQUIP == stShopConfigData._ucItemType)
    {
        unsigned int uiEquipID = 0;
        if (CShopMgr::SHOP_TYPE_BUYBACK == ucShopType) //回购直接向背包发送道具
        {
            CShopBuyBackItem stBuyBackItem;
            iRet = pstMainCtrl->m_stShopMgr.TakeoutBuyBackItem(stPlayerOnlineData._stUserShop, usItemPos, stBuyBackItem);
            if (iRet != RET_OK)
            {
                CT_WARNING(("Take out item from buyback list err. ItemPos: %u. %d", usItemPos, _uiGID));
                return AnsClients(iRet);
            }

            //添加到装备系统后,再加入到背包
            pstMainCtrl->m_stEquipMgr.AddBuyBackEquip(stBuyBackItem, stPlayerOnlineData._stUserEquip,stPlayerOnlineData._stUserStorage);

            uiEquipID = stBuyBackItem._uiItemID;
        }
        else
        {
            //如果是装备,生成装备ID后, 再加入到背包
            
            iRet = pstMainCtrl->m_stEquipMgr.AddEquip(stPlayerOnlineData._stUserEquip,
                stShopConfigData._usItemConfigID, stPlayerOnlineData._stUserStorage, uiEquipID);
            if (RET_OK != iRet)
            {
                CT_WARNING(("Add shop item to bag err. ItemPos: %u, equipcfgid: %u, ret: %u", usItemPos, stShopConfigData._usItemConfigID,iRet));
            }           
        }

        stNewItem._iData1 = uiEquipID;
        pstMainCtrl->m_stEquipMgr.GetData(stPlayerOnlineData._stUserEquip, stPlayerDetailInfo._stUserEquip);
    }
    else
    {
        if (CShopMgr::SHOP_TYPE_BUYBACK == ucShopType) //回购直接向背包发送道具
        {
            CShopBuyBackItem stBuyBackItem;
            iRet = pstMainCtrl->m_stShopMgr.TakeoutBuyBackItem(stPlayerOnlineData._stUserShop, usItemPos, stBuyBackItem);
            if (iRet != RET_OK)
            {
                CT_WARNING(("Takeout buyback item failed.ret: %u, item_type: %u, item_id: %u",iRet, stBuyBackItem._ucItemType, stBuyBackItem._uiItemID));
            }

            CStorageGrid stItemGrid;
            stItemGrid.Init(stBuyBackItem._ucItemType, stBuyBackItem._uiItemID);
            stItemGrid._shCount = stBuyBackItem._usItemCount;
            stItemGrid._iInvalidTime = stBuyBackItem._iInvalidTime;

            //添加到背包
            iRet = stPlayerOnlineData._stUserStorage.AddToBag(stItemGrid);
            if (RET_OK != iRet)
            {
                CT_WARNING(("Add backlist item to bag failed. iRet: %u", iRet));
            }
        }
        else
        {
            CStorageGrid stItemGrid;
            stItemGrid.Init(stShopConfigData._ucItemType, stShopConfigData._usItemConfigID);
            stItemGrid._shCount = stShopConfigData._usItemCount;
            iRet = stPlayerOnlineData._stUserStorage.AddToBag(stItemGrid);
            if (iRet)
            {
                CT_WARNING(("add item count error,uid %u left %d, %d, %d", _uiGID,
                    stShopConfigData._ucItemType, stShopConfigData._usItemConfigID, stShopConfigData._usItemCount));
            }
        }
    }

    iRet = AfterBuyItem(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    //保存数据
    pstMainCtrl->m_stStorageMgr.GetData(stPlayerOnlineData._stUserStorage, stPlayerDetailInfo._stUserStorage);
    if (CShopMgr::SHOP_TYPE_MYSTICAL == ucShopType
        || CShopMgr::SHOP_TYPE_CLAN == ucShopType
        || CShopMgr::SHOP_TYPE_CRYSTAL == ucShopType)
    {
        pstMainCtrl->m_stShopMgr.GetData(stPlayerOnlineData._stUserShop, stPlayerDetailInfo._stShopData);
    }

    pstMainCtrl->m_stOssMgr.TriggerItem(stPlayerBaseInfo._uiGID, OSS_ITEM_SHOP_BUY);//oss

    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_BASE_INFO;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);


    stAns.set_shop_type(stReq.shop_type());
    stAns.set_item_pos(stReq.item_pos());
    CTSizeString<64>  sSilver;
    sSilver.Set("%u", stPlayerBaseInfo._i64Silver);
    stAns.set_silver(sSilver());
    stAns.set_gold(stPlayerBaseInfo._iGold);

    _uiNotify |= (NOTIFY_USER_MONEY | NOTIFY_BAG_INFO);

    //通知前台,背包格子变化
    stNewItem._ucItemType = stShopConfigData._ucItemType;
    stNewItem._usItemConfigID = stShopConfigData._usItemConfigID;
    stNewItem._iItemCount = stShopConfigData._usItemCount;
    pstMainCtrl->m_stItemMgr.NotifyDropItem(_uiGID, stNewItem);
    return AnsClients(iRet);
}

int CCmdShopBuyItem::AnsClients(int iRet)
{
    if (_uiNotify)
    {
        pstMainCtrl->m_stNotifyMgr.Notify(_uiGID, _uiNotify);
    }
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgid(ID_MAIN_SHOP_BUY);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

	stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

int CCmdShopBuyItem::PreCheck (CPlayerBaseInfo & stPlayerBaseInfo,  CPlayerDetailInfo & stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData)
{
    unsigned char ucShopType = stReq.shop_type() & 0x7F;
    unsigned short usItemPos = stReq.item_pos() & 0x7FFF;

    //判断背包中是否已满
    if (stPlayerOnlineData._stUserStorage.BagIsFull())
    {
        return ERROR_SHOP_BAG_ISFULL;
    }

    int iRet = RET_OK;

    //购买家族商店物品前,先判断商店物品是否需要刷新
    bool bNeedUpdateDetail = false;
    if (CShopMgr::SHOP_TYPE_CLAN == ucShopType)
    {
        //第一天MAX_CLAN_SHOP_REFRESH_TIME前加入家族的,限制购买物品. (防止刷物品) TASK #224::家族优化
        if (stPlayerDetailInfo._stUserClan.HasJoinedClanBefore() && CTTimeUtils::IsSameDay(stPlayerDetailInfo._stUserClan._iJoinTime, pstMainCtrl->m_iNow, 0))
        {
            return ERROR_CLAN_SHOP_TIME;
        }

        iRet = pstMainCtrl->m_stClanMgr.RefreshShop (stPlayerDetailInfo._stUserClan._uiClanId);
        if (iRet)
        {
            return iRet;
        }

        //重置购买到的物品
        if (!CTTimeUtils::IsSameDay(pstMainCtrl->m_iNow, stPlayerOnlineData._stUserShop._stClanShop._iLastBuyTime, MAX_CLAN_SHOP_REFRESH_TIME))
        {
            stPlayerOnlineData._stUserShop._stClanShop._astBuyItems.Clear();
            stPlayerOnlineData._stUserShop._stClanShop._iLastBuyTime = CMainCtrl::m_pstMain->m_iNow;
            bNeedUpdateDetail = true;
        }
    }

    if (CShopMgr::SHOP_TYPE_CRYSTAL == ucShopType)
    {
        //判断活动是否打开
        if (false == pstMainCtrl->m_stActMgr.IsActOpen(ACT_ID_WEEKEND_SHOP))
        {
            CT_WARNING(("crystal shop isn't open. %d, %d", pstMainCtrl->m_iNow, _uiGID));
            return ERROR_CRYSTAL_SHOP_NOT_OPEN;
        }

        if (pstMainCtrl->m_iNow > stPlayerOnlineData._stUserShop._iClearCrystalShopTime)
        {
            stPlayerOnlineData._stUserShop._astCrystalItems.Clear();
            stPlayerOnlineData._stUserShop._iClearCrystalShopTime = pstMainCtrl->m_stActMgr.GetEndTime(ACT_ID_WEEKEND_SHOP);

            bNeedUpdateDetail = true;
        }
    }

    if (bNeedUpdateDetail)
    {
        pstMainCtrl->m_stShopMgr.GetData(stPlayerOnlineData._stUserShop, stPlayerDetailInfo._stShopData);
        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        CMainCtrl::m_pstMain->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }    

    //获取商品的售价
    iRet = pstMainCtrl->m_stShopMgr.GetShopItem (stPlayerBaseInfo._shLevel, ucShopType, usItemPos, stPlayerOnlineData._stUserShop, stShopConfigData);
    if (iRet != RET_OK)
    {
        return iRet;
    }

    //如果是装备，判断是否能够获取
    if (ITEM_TYPE_EQUIP == stShopConfigData._ucItemType)
    {
        iRet = stPlayerOnlineData._stUserEquip.CheckBeforeAdd(stShopConfigData._usItemConfigID);
        CHECK_RETURN(iRet);
    }

    //神秘商店物品已经被购买过了
    if ((CShopMgr::SHOP_TYPE_MYSTICAL == ucShopType) &&
        (SHOP_ITEM_SALE_OUT == stShopConfigData._usExchangeItemID))
    {
        return ERROR_MYST_ALREADY_BUY;
    }

    //家族商店是否已经买过
    if ((CShopMgr::SHOP_TYPE_CLAN == ucShopType) &&
        (SHOP_ITEM_SALE_OUT == stShopConfigData._usExchangeItemID))
    {
        return ERROR_CLAN_ALREADY_BUY;
    }

    if (CShopMgr::SHOP_TYPE_CRYSTAL == ucShopType)
    {
        if (SHOP_ITEM_SALE_OUT == stShopConfigData._usExchangeItemID)
        {
            return ERROR_CRYSTAL_SHOP_ALREADY_BUY;
        }

        int iCount = pstMainCtrl->m_stStorageMgr.GetItemCount(stPlayerOnlineData._stUserStorage, ITEM_TYPE_SEAL, 1);
        if (iCount < stShopConfigData._usDiscount)
        {
            return ERROR_CRYSTAL_SHOP_LACK;
        }
    }

    return 0;
}

int CCmdShopBuyItem::AfterBuyItem(CPlayerBaseInfo & stPlayerBaseInfo,  CPlayerDetailInfo & stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData)
{
    unsigned char ucShopType = stReq.shop_type() & 0x7F;
    unsigned short usPos = stReq.item_pos() & 0x7FFF;

    //如果是从回购商店中购买的,需要刷新回购列表
    int iRet;
    if (CShopMgr::SHOP_TYPE_BUYBACK == ucShopType)
    {
        pstMainCtrl->m_stShopMgr.SendBuyBackItemList(stPlayerOnlineData._stUserShop, stMsgHead, stEnpHead);
    }

    if (CShopMgr::SHOP_TYPE_MYSTICAL == ucShopType)
    {
        CShopItemConfig & stShopItem = stPlayerOnlineData._stUserShop._stMysticalShop._astShopItem[usPos];
        stShopItem._usExchangeItemID = SHOP_ITEM_SALE_OUT;

        //刷新神秘商店购买历史
        if ((ITEM_TYPE_SCROLL == stShopItem._ucItemType)
            || (ITEM_TYPE_CRYSTAL == stShopItem._ucItemType))
        {
            CShopHistoryItemData stHistoryItem;
            stHistoryItem._uiGid = _uiGID;
            stHistoryItem._ucItemType = stShopItem._ucItemType;
            stHistoryItem._usItemId = stShopItem._usItemConfigID;
            pstMainCtrl->m_stShopMgr.UpdateHistory(stHistoryItem);
        }
    }

    //宝石商店，记录购买的时间
    if (CShopMgr::SHOP_TYPE_CRYSTAL == ucShopType)
    {
        stPlayerOnlineData._stUserShop._astCrystalItems.AddOneItem(usPos);
    }

    //家族商店，记录购买的时间
    if (CShopMgr::SHOP_TYPE_CLAN== ucShopType)
    {
        stPlayerOnlineData._stUserShop._stClanShop._iLastBuyTime = pstMainCtrl->m_iNow;
        iRet = stPlayerOnlineData._stUserShop.AddClanShopItem((unsigned char)usPos);
        CHECK_RETURN(iRet);
    }

    return 0;
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_SHOP_SELL, CCmdShopSellItem);
int CCmdShopSellItem::Do(void* pData)
{
    CT_ASSERT(pData);

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_SHOP_SELL ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_SHOP_SELL,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdShopSellItem::GetSoldItem (CStorageGrid &stGrid, CShopBuyBackItem & stBuyBackItem)
{
	int iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
	CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    int iRet;
    int iSilverPrice = 0;
    if (stGrid._stKey._ucItemType == ITEM_TYPE_EQUIP)
    {
        CSingleEquip stSingleEquip;
        iRet = pstMainCtrl->m_stEquipMgr.GetEquip(stPlayerOnlineData._stUserEquip, stGrid._stKey._uiItemID, stSingleEquip);
        CHECK_RETURN(iRet);

        int iRet = pstMainCtrl->m_stEquipMgr.CheckEquipAddOns(stSingleEquip);
        CHECK_RETURN(iRet);

        iRet = pstMainCtrl->m_stEquipMgr.GetEquipSellPrice(stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel, iSilverPrice);
        CHECK_RETURN(iRet);

        stBuyBackItem._uiItemConfigId = stSingleEquip._usEquipConfigID;
        stBuyBackItem._usLevel = stSingleEquip._usStrengthenLevel;
        stBuyBackItem._stRefineAndBlessStats = stSingleEquip._stRefineAndBlessStats;
    }
    else
    {
        iRet = pstMainCtrl->m_stItemMgr.GetItemPrice(stGrid._stKey._ucItemType, stGrid._stKey._uiItemID,
                                                         stGrid._shCount, ITEM_SELL_PRICE, iSilverPrice);
        CHECK_RETURN(iRet);

        stBuyBackItem._uiItemConfigId = stGrid._stKey._uiItemID;
    }

    stBuyBackItem._ucItemType = stGrid._stKey._ucItemType;
    stBuyBackItem._uiItemID = stGrid._stKey._uiItemID;
    stBuyBackItem._usItemCount = stGrid._shCount;
    stBuyBackItem._uiPrice = iSilverPrice;
    stBuyBackItem._iInvalidTime = stGrid._iInvalidTime;

    return 0;
}

int CCmdShopSellItem::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    ASSERT_PLAYER_PREPARED(stReq.gid());

    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    ASSERT_PLAYER_DETAIL_PREPARED(stReq.gid());

    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
	CPlayerBaseInfo & stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo & stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

	iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
	CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];
    CUserStorage& stUserStorage =  stPlayerOnlineData._stUserStorage;

    CStorageGrid stGrid;
    iRet = pstMainCtrl->m_stStorageMgr.GetGridInfoByPos(stUserStorage, true, stReq.item_pos(), stGrid);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    bool bCanSell;
    iRet = pstMainCtrl->m_stItemMgr.CheckCanOper(stGrid._stKey._ucItemType, stGrid._stKey._uiItemID,
                                                ITEM_OPER_SELL, bCanSell);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    if (!bCanSell)
    {
        return AnsClients(ERROR_ITEM_CANNOT_SELL);
    }

    //获取保存到回购列表中的结构
    CShopBuyBackItem stBuyBackItem;
    iRet = GetSoldItem (stGrid, stBuyBackItem);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss

    //从装备管理器中取出装备
    if (stGrid._stKey._ucItemType == ITEM_TYPE_EQUIP)
    {
        iRet = pstMainCtrl->m_stEquipMgr.DelEquip(stPlayerOnlineData._stUserEquip, stGrid._stKey._uiItemID);
        if (iRet)
        {
            return AnsClients(iRet);
        }
    }

    //从背包中取出物品
    iRet = pstMainCtrl->m_stStorageMgr.TakeOutGrid(stPlayerOnlineData._stUserStorage, stGrid._stKey._usStorePos, stGrid);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    //加入到回购列表
    iRet = pstMainCtrl->m_stShopMgr.AddBuyBackItem(stPlayerOnlineData._stUserShop, stBuyBackItem, stPlayerOnlineData);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    iRet = CPlayerBaseInfo::AddSilver(stPlayerBaseInfo._i64Silver, stBuyBackItem._uiPrice);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    //保存数据
    if (ITEM_TYPE_EQUIP == stGrid._stKey._ucItemType)
    {
        pstMainCtrl->m_stEquipMgr.GetData(stPlayerOnlineData._stUserEquip, stPlayerDetailInfo._stUserEquip);
    }

    pstMainCtrl->m_stStorageMgr.GetData(stPlayerOnlineData._stUserStorage, stPlayerDetailInfo._stUserStorage);

    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_BASE_INFO;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);

    //发送回购列表到前台
    pstMainCtrl->m_stShopMgr.SendBuyBackItemList(stPlayerOnlineData._stUserShop, stMsgHead, stEnpHead);

    pstMainCtrl->m_stOssMgr.TriggerItem(_uiGID, OSS_ITEM_SELL_LIST);//oss

    CTSizeString<64>  sSilver;
    sSilver.Set("%u", stPlayerBaseInfo._i64Silver);
    stAns.set_silver(sSilver());
    stAns.set_bag_pos(stGrid._stKey._usStorePos);

    pstMainCtrl->m_stNotifyMgr.Notify(_uiGID, NOTIFY_USER_MONEY);

	return AnsClients(RET_OK);
}

int CCmdShopSellItem::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    stMsgHead.set_msgid(ID_MAIN_SHOP_SELL);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_REFRESH_SHOP, CCmdShopRefreshItem);

int CCmdShopRefreshItem::Do(void* pData)
{
    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_REFRESH_SHOP ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_REFRESH_SHOP,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdShopRefreshItem::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, _uiGID);
    ASSERT_PLAYER_PREPARED(_uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, _uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(_uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, _uiGID);

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo & stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo & stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    unsigned char ucShopType = stReq.shop_type() & 0x7F;
    unsigned char ucRefreshType = stReq.refresh_type() & 0x7F;

    if ( ucShopType != CShopMgr::SHOP_TYPE_MYSTICAL)
    {
        return AnsClients(ERROR_UNSUPPORT_REFRESH_TYPE);
    }

    CMysticalShop & stMystShop = stPlayerOnlineData._stUserShop._stMysticalShop;
    int iNeedGold = 0;
    switch (ucRefreshType)
    {
        case MYSTICAL_UPDATE_GOLD:
            {
                 iNeedGold = stMystShop.GetGoldRefreshCost();
                 if (iNeedGold > stPlayerBaseInfo._iGold)
                 {
                    return AnsClients(ERROR_GOLD_LESS);
                 }
            }
            break;

        case MYSTICAL_UPDATE_CANE:
            {
                if (stMystShop._ucCaneCnt < 1)
                {
                    return AnsClients(ERROR_LACK_MYST_CANE);
                }
            }
            break;
        default:
            {
                return AnsClients(ERROR_UNSUPPORT_REFRESH_TYPE);
            }
    }

    iRet = pstMainCtrl->m_stShopMgr.RefreshShopItem(stPlayerBaseInfo._uiGID, stPlayerOnlineData._stUserShop,
                                                    stPlayerBaseInfo._shLevel, ucRefreshType);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    CVarObjectKey stKey;
    if (MYSTICAL_UPDATE_CANE == ucRefreshType)
    {
        stMystShop._ucCaneCnt -= 1;
    }
    else
    {
        stMystShop._ucGoldRefreshCnt += 1;
        //扣除金币
        iRet = pstMainCtrl->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_18, iNeedGold);
        if (RET_OK != iRet)
        {
            return AnsClients(iRet);
        }

        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);
    }

    pstMainCtrl->m_stShopMgr.GetData(stPlayerOnlineData._stUserShop, stPlayerDetailInfo._stShopData);

    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);

    //触发任务
    CMainCtrl::m_pstMain->m_stDailyTaskMgr.TriggerTaskFinish(stPlayerOnlineData._stUserDailyTask, DAILY_TASK_ID_29);

    pstMainCtrl->m_stShopMgr.SendInfoToFront(stPlayerBaseInfo._shLevel, stPlayerOnlineData._stUserShop, CShopMgr::SHOP_TYPE_MYSTICAL,
                                             stMsgHead, stEnpHead);

    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerDetailInfo._uiGID, NOTIFY_USER_MONEY);

    return AnsClients(RET_OK);
}

int CCmdShopRefreshItem::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->m_stEncodeBuf.Clear();
    MsgAnsRefreshItem stAns;   //仅为前台展示用
    stAns.set_data(1);
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}
